package com.ruoyi.tester.executor;

import com.mashape.unirest.http.HttpResponse;
import com.ruoyi.tester.domain.InterfaceCallLog;
import com.ruoyi.tester.domain.InterfaceCallStatus;
import com.ruoyi.tester.domain.TaskCallProgres;
import com.ruoyi.tester.domain.TaskInterfaceEffectiveInfo;
import com.ruoyi.tester.executor.http.HttpUtils;
import com.ruoyi.tester.executor.http.HttpUtilsFactory;
import com.ruoyi.tester.executor.http.XzfHttpResult;
import com.ruoyi.tester.login.Login;
import com.ruoyi.tester.login.LoginHandlerContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author SongJun
 * @description TODO:
 * @date 2022/4/15 15:54
 */
public class InterfaceCallable implements Runnable {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private TaskInterfaceEffectiveInfo interfaceInfo;
    private IExtraHandler extraHandler;
    private List<TaskInterfaceEffectiveInfo> effectiveList;
    private Map<Long, String> calledStatus;

    public InterfaceCallable(TaskInterfaceEffectiveInfo interfaceInfo, IExtraHandler extraHandler, List<TaskInterfaceEffectiveInfo> effectiveList, Map<Long, String> calledStatus){
        this.interfaceInfo = interfaceInfo;
        this.extraHandler = extraHandler;
        this.calledStatus = calledStatus;
        this.effectiveList = effectiveList;
    }

    @Override
    public void run() {
        Map<String, String> headers = new HashMap<>();
        String response = null;
        Map<String, String> responseHeaders = new HashMap<>();
        String exception = null;
        String interfaceStatus = null;
        String taskProgres = null;
        try {
            Login loginHandler = LoginHandlerContainer.getLoginHandler(interfaceInfo.getLoginConfigId());
            if (loginHandler != null) {
//                logger.info("{}获取{}的header", Thread.currentThread().getId(), interfaceInfo.getInterfaceDesc());
                headers = loginHandler.makeHeaders(interfaceInfo.getLoginConfigId());
            }

            XzfHttpResult xzfHttpResult = null;
            try {
                extraHandler.cureDependParam(interfaceInfo, calledStatus);
                xzfHttpResult = InterfaceCallUtils.execute(interfaceInfo, headers);
                response = xzfHttpResult.getBody();
                responseHeaders = xzfHttpResult.getHeaders();
            } catch (Exception e){
                logger.error("接口调用异常interfaceInfo={}, {}", interfaceInfo, e);
                exception = e.getMessage();
                taskProgres = TaskCallProgres.FAULT;
                interfaceStatus = InterfaceCallStatus.FAULT;
                throw e;
            }

            calledStatus.put(interfaceInfo.getRelationId(), response);

            try {
                if (extraHandler.judgeResponse(interfaceInfo, xzfHttpResult)) {
                    interfaceStatus = InterfaceCallStatus.SUCCESS;
                    if (calledStatus.size() >= effectiveList.size()) {
                        taskProgres = TaskCallProgres.PERFECT;
                    }
                } else {
                    taskProgres = TaskCallProgres.FAULT;
                    interfaceStatus = InterfaceCallStatus.FAULT;
                }
            } catch (Exception e){
                logger.error("处理调用结果异常interfaceInfo={}, {}", interfaceInfo, e);
                exception = e.getMessage();
                taskProgres = TaskCallProgres.FAULT;
                interfaceStatus = InterfaceCallStatus.FAULT;
                throw e;
            }

            List<TaskInterfaceEffectiveInfo> followedList = extraHandler.followedInterfaceInfoList(interfaceInfo.getRelationId(), effectiveList, calledStatus);
            for (TaskInterfaceEffectiveInfo item : followedList) {
                InterfaceExecutorUtil.callInterface(item, extraHandler, effectiveList, calledStatus);
            }
        }catch (Exception e){
            logger.error("执行调用接口异常interfaceInfo={}, {}", interfaceInfo, e);
            exception = e.getMessage();
            taskProgres = TaskCallProgres.FAULT;
            interfaceStatus = InterfaceCallStatus.FAULT;
        }finally {
            InterfaceCallLog interfaceCallLog = new InterfaceCallLog(interfaceInfo, headers, response, responseHeaders, exception);
            interfaceCallLog.setStatus(interfaceStatus);
            extraHandler.saveResult(interfaceCallLog, taskProgres);
        }
    }
}
